﻿using System.Collections.ObjectModel;
using System.Windows;
using Avalonia;
using Avalonia.Controls;
using KinonekoSoftware.ArkSpark.Core;
using KinonekoSoftware.ArkSpark.Services.Highlighting;
using KinonekoSoftware.ArkSpark.Services.Highlights;
using KinonekoSoftware.Extensions.Ioc;

namespace KinonekoSoftware.ArkSpark.Helpers
{
    /// <summary>
    /// 实现TextBlock的高亮显示。
    /// </summary>
    public class Highlight : AvaloniaObject
    {
        public static readonly AttachedProperty<IList<IHighlightToken>> HighlightSourceProperty;
        public static readonly AttachedProperty<int>                    HighlightInfoChangedProperty;

        static Highlight()
        {
            HighlightSourceProperty      = AvaloniaProperty.RegisterAttached<Highlight, TextBlock, IList<IHighlightToken>>("HighlightSource");
            HighlightInfoChangedProperty = AvaloniaProperty.RegisterAttached<Highlight, TextBlock, int>("HighlightInfoChanged");
            HighlightSourceProperty.Changed.Subscribe(OnHighlightSourceChanged);
            HighlightInfoChangedProperty.Changed.Subscribe(OnHighlightInfoChanged);
        }

        public static void SetHighlightInfoChanged(TextBlock element, int value)
        {
            element.SetValue(HighlightInfoChangedProperty, value);
        }

        public static int GetHighlightInfoChanged(TextBlock element)
        {
            return (int)element.GetValue(HighlightInfoChangedProperty);
        }

        private static void OnHighlightInfoChanged(AvaloniaPropertyChangedEventArgs<int> e)
        {
            if (e.Sender is TextBlock visual && visual.DataContext is IHighlightDataContext context)
            {
                HighlightThis(visual, context, context.GetHighlightGlossaries());
            }
        }

        private static void OnHighlightSourceChanged(AvaloniaPropertyChangedEventArgs<IList<IHighlightToken>> e)
        {
            var highlightGlossaries = e.GetNewValue<IList<IHighlightToken>>();

            if (e.Sender is TextBlock visual                        &&
                visual.DataContext is IHighlightDataContext context &&
                highlightGlossaries is not null)
            {
                HighlightThis(visual, context, highlightGlossaries);
            }

        }

        private static void HighlightThis(TextBlock visual, IHighlightDataContext context, IList<IHighlightToken> highlightGlossaries)
        {
            if (highlightGlossaries.Count == 0)
            {
                return;
            }

            if (highlightGlossaries.Count == 1 && !highlightGlossaries[0].Segment.IsMatch)
            {
                visual.Text = highlightGlossaries[0].Name;
            }
            else
            {
                var style = HighlightStyle ?? DefaultHighlightVisualStyle.Instance;
                style.reStyle(visual, highlightGlossaries, context.Content);
            }
        }


        public static void SetHighlightSource(AvaloniaObject element, string value)
        {
            element.SetValue(HighlightSourceProperty, value);
        }

        public static IList<IHighlightToken> GetHighlightSource(AvaloniaObject element)
        {
            return element.GetValue(HighlightSourceProperty);
        }


        public static IHighlightVisualStyle HighlightStyle { get; set; }
    }
}